package com.atguigu;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName ProdConsumerDemo
 * @Author yy
 * @create 2022/9/7 19:59
 */

//线程间通信   (只有两个线城时,不会发生线程的虚假唤醒)

/*
 * 有一个初始值为零的变量，现有两个线程对该变量操作，
 * 实现一个线程对变量加1，
 * 实现一个线程对变量减1,
 * 交替来10轮
 *
 * 1 高内聚低耦合前提下，线程   操作      资源类
 *
 * 2 判断、干活、通知
 *
 * 3 防止线程的虚假唤醒
 *      使用if会造成虚假唤醒(因为if只唤醒一次)
 *      而While不会造成虚假唤醒(while只要唤醒就会拉回来继续比较一次)
 *
 * 4 多线程的标志位变更
 */

class AirCondition{

    //运用synchronized
    /*private int number = 0;

    public synchronized void add() throws InterruptedException {
        //判断
        while (number != 0){
            this.wait();
        }
        //干活
        System.out.println(Thread.currentThread().getName() + "\t" + (++number));
        //通知
        this.notifyAll();
    }

    public synchronized void dev() throws InterruptedException {
        //判断
        while (number == 0){
            this.wait();
        }
        //干活
        System.out.println(Thread.currentThread().getName()+"\t"+(--number));
        //通知
        this.notifyAll();
    }*/



    //====================JUC新版

    private int number = 0;
    private Lock lock = new ReentrantLock();
    private Condition condition = lock.newCondition();

    public void add(){
        lock.lock();
        try {
            //判断
            while (number != 0){
                condition.await();
            }
            //干活
            System.out.println(Thread.currentThread().getName()+"\t"+(++number));
            //通知
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void dev(){
        lock.lock();
        try {
            //判断
            while (number == 0){
                condition.await();
            }
            //干活
            System.out.println(Thread.currentThread().getName()+"\t"+(--number));
            //通知
            condition.signalAll();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}

public class ProdConsumerDemo {
    public static void main(String[] args) {
        AirCondition airCondition = new AirCondition();

        new Thread(()->{
            for (int i = 0; i < 10; i++) airCondition.add();
        },"A").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) airCondition.dev();
        }, "B").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) airCondition.add();
        }, "C").start();

        new Thread(() -> {
            for (int i = 0; i < 10; i++) airCondition.dev();
        }, "D").start();
    }
}
